"""
认证相关API端点
"""

from fastapi import APIRouter, Depends, HTTPException, status, Request
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Dict, Any

from app.core.database import get_db
from app.core.dependencies import (
    get_current_user, get_current_active_user, check_login_rate_limit
)
from app.models.auth import User
from app.schemas.auth import (
    LoginRequest, LoginResponse, RegisterRequest, RegisterResponse,
    ChangePasswordRequest, TokenRefreshRequest, TokenResponse,
    UserProfile, ResetPasswordRequest
)
from app.schemas.common import BaseResponse
from app.services.auth_service import AuthService
from app.utils.timezone_utils import get_shanghai_now
from app.core.logger import logger

router = APIRouter()
auth_service = AuthService()


@router.post("/login", response_model=BaseResponse[LoginResponse])
async def login(
    request: Request,
    login_data: LoginRequest,
    db: AsyncSession = Depends(get_db),
    _: bool = Depends(check_login_rate_limit)
):
    """
    用户登录
    
    - **username**: 用户名或邮箱地址
    - **password**: 密码
    - **remember_me**: 是否记住登录状态
    """
    try:
        result = await auth_service.login(db, login_data, request)
        
        return BaseResponse(
            data=result,
            message="登录成功",
            success=True
        )
    except HTTPException as e:
        logger.warning(f"登录失败：{e.detail}")
        raise e
    except Exception as e:
        logger.error(f"登录异常：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="登录服务异常"
        )


@router.post("/register", response_model=BaseResponse[RegisterResponse])
async def register(
    register_data: RegisterRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    用户注册

    - **username**: 用户名（3-50字符，只允许字母、数字、下划线）
    - **email**: 邮箱地址
    - **password**: 密码（至少8字符，包含大小写字母、数字、特殊字符）
    - **confirm_password**: 确认密码
    - **full_name**: 真实姓名（可选）
    - **phone**: 手机号码（可选）
    - **department**: 部门（可选）
    - **position**: 职位（可选）
    """
    try:
        # 添加调试日志
        logger.info(f"收到注册请求: {register_data.model_dump()}")

        user = await auth_service.register(db, register_data)

        return BaseResponse(
            data=RegisterResponse(
                message="注册成功，请联系管理员激活账户",
                user=user
            ),
            message="注册成功",
            success=True
        )
    except HTTPException as e:
        logger.warning(f"注册失败：{e.detail}")
        raise e
    except Exception as e:
        logger.error(f"注册异常：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="注册服务异常"
        )


@router.post("/logout", response_model=BaseResponse[Dict[str, str]])
async def logout(
    request: Request,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """
    用户登出
    """
    try:
        # 从请求头获取token
        auth_header = request.headers.get("Authorization")
        token = auth_header.split(" ")[1] if auth_header and auth_header.startswith("Bearer ") else None
        
        await auth_service.logout(db, current_user, token)
        
        return BaseResponse(
            data={"message": "登出成功"},
            message="登出成功",
            success=True
        )
    except Exception as e:
        logger.error(f"登出异常：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="登出服务异常"
        )


@router.post("/refresh", response_model=BaseResponse[TokenResponse])
async def refresh_token(
    refresh_data: TokenRefreshRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    刷新访问令牌
    
    - **refresh_token**: 刷新令牌
    """
    try:
        result = await auth_service.refresh_token(db, refresh_data.refresh_token)
        
        return BaseResponse(
            data=TokenResponse(**result),
            message="令牌刷新成功",
            success=True
        )
    except HTTPException as e:
        logger.warning(f"令牌刷新失败：{e.detail}")
        raise e
    except Exception as e:
        logger.error(f"令牌刷新异常：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="令牌刷新服务异常"
        )


@router.get("/me", response_model=BaseResponse[UserProfile])
async def get_current_user_profile(
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db)
):
    """
    获取当前用户信息 - 使用完整的用户对象序列化
    """
    try:
        # 重新查询用户以确保关联数据完整加载
        from sqlalchemy import select
        from sqlalchemy.orm import selectinload
        from app.models.auth import UserRole, Role, RolePermission

        stmt = select(User).where(User.id == current_user.id).options(
            selectinload(User.user_roles).selectinload(UserRole.role).selectinload(Role.role_permissions).selectinload(RolePermission.permission)
        )
        result = await db.execute(stmt)
        user_with_full_data = result.scalar_one_or_none()

        if not user_with_full_data:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )

        # 直接使用User对象，让UserProfile的@root_validator处理序列化
        user_profile = UserProfile.from_orm(user_with_full_data)

        return BaseResponse(
            data=user_profile,
            message="获取用户信息成功",
            success=True
        )
    except Exception as e:
        logger.error(f"获取用户信息异常：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取用户信息失败"
        )


@router.post("/change-password", response_model=BaseResponse[Dict[str, str]])
async def change_password(
    password_data: ChangePasswordRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """
    修改密码
    
    - **current_password**: 当前密码
    - **new_password**: 新密码（至少8字符，包含大小写字母、数字、特殊字符）
    - **confirm_password**: 确认新密码
    """
    try:
        from app.core.security import verify_password, get_password_hash
        from datetime import datetime
        
        # 验证当前密码
        if not verify_password(password_data.current_password, current_user.password_hash):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="当前密码错误"
            )
        
        # 检查新密码是否与当前密码相同
        if verify_password(password_data.new_password, current_user.password_hash):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="新密码不能与当前密码相同"
            )
        
        # 更新密码
        current_user.password_hash = get_password_hash(password_data.new_password)
        current_user.password_changed_at = get_shanghai_now()
        current_user.updated_at = get_shanghai_now()
        
        await db.commit()
        
        logger.info(f"用户修改密码成功：{current_user.username}")
        
        return BaseResponse(
            data={"message": "密码修改成功"},
            message="密码修改成功",
            success=True
        )
    except HTTPException as e:
        logger.warning(f"修改密码失败：{e.detail}")
        raise e
    except Exception as e:
        logger.error(f"修改密码异常：{str(e)}")
        await db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="修改密码服务异常"
        )


@router.post("/reset-password", response_model=BaseResponse[Dict[str, str]])
async def reset_password(
    reset_data: ResetPasswordRequest,
    db: AsyncSession = Depends(get_db)
):
    """
    重置密码（发送重置邮件）
    
    - **email**: 邮箱地址
    """
    try:
        from sqlalchemy import select
        
        # 查找用户
        stmt = select(User).where(User.email == reset_data.email)
        result = await db.execute(stmt)
        user = result.scalar_one_or_none()
        
        if not user:
            # 为了安全，即使用户不存在也返回成功消息
            return BaseResponse(
                data={"message": "如果邮箱存在，重置链接已发送"},
                message="重置邮件发送成功",
                success=True
            )
        
        if not user.is_active:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="账户未激活"
            )
        
        # TODO: 实现邮件发送功能
        # 这里应该生成重置令牌并发送邮件
        # reset_token = generate_password_reset_token(user.email)
        # await send_reset_password_email(user.email, reset_token)
        
        logger.info(f"密码重置请求：{user.email}")
        
        return BaseResponse(
            data={"message": "重置链接已发送到您的邮箱"},
            message="重置邮件发送成功",
            success=True
        )
    except HTTPException as e:
        logger.warning(f"密码重置失败：{e.detail}")
        raise e
    except Exception as e:
        logger.error(f"密码重置异常：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="密码重置服务异常"
        )


@router.get("/check-token", response_model=BaseResponse[Dict[str, Any]])
async def check_token(
    current_user: User = Depends(get_current_user)
):
    """
    检查令牌有效性
    """
    try:
        return BaseResponse(
            data={
                "valid": True,
                "user_id": current_user.id,
                "username": current_user.username,
                "is_active": current_user.is_active,
                "is_superuser": current_user.is_superuser
            },
            message="令牌有效",
            success=True
        )
    except Exception as e:
        logger.error(f"检查令牌异常：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="令牌无效"
        )
